import api from './api'

const {StatusBar, AsyncStorage} = require('react-native');
const moment = require('moment');
const {Toast} = require('antd-mobile');
import constant from "./constant";
import Validator from "./Validator";
import RouterServer from "./RouterServer";

let instance = null;

export interface Response {
    code: number,
    message?: string | object | object[] | string[],
    status?: string | object | object[] | string[],
    data?: object
}

export interface API {
    HOST: string,
}

class Request {

    Api: API;
    debug: boolean;


    timeout: number;

    /**
     * 接口
     * @return {(() => (() => any) | API | any) | API | any}
     * @constructor
     */
    static getApi() {
        return Request.getInstance().Api;
    };


    /**
     *
     * @param {API} api
     * @param {boolean} debug
     * @param {number} timeout
     */
    static init(api: API, debug = true, timeout = 5000) {
        Request.getInstance().Api = api;
        Request.getInstance().debug = debug;
        Request.getInstance().timeout = timeout;
    }

    static getInstance() {
        if (!instance) {
            instance = new Request();
        }
        return instance;
    }

    /**
     * 参数拼接 将对象拼接成 key=value&key=value 的形式
     * @param {Object} params
     * @return {string}
     */
    static makeQueryString = (params?: object) => {
        if (!params) {
            return ''
        }
        let query = [];
        for (let key in params) {
            if (!params.hasOwnProperty(key)) {
                continue
            }
            query.push(`${key}=${params[key]}`)
        }
        return '?' + query.join('&')
    };

    /**
     * 拼接表单参数
     * @param {Object} params
     * @return {FormData}
     */
    static makeFormData = (params: object) => {
        const formData = new FormData();
        for (let key in params) {
            if (!params.hasOwnProperty(key)) {
                continue
            }
            formData.append(key, params[key])
        }
        return formData
    };


    /**
     * 检查响应
     * @param {Response} response
     * @param apiUrl
     * @return {Promise<Response>}
     */
    static checkResponse(response: Response, apiUrl) {
        StatusBar.setNetworkActivityIndicatorVisible(false);
        if (response.code === 200) {
            return true;
        }
        else {
            if (Request.getInstance().debug) {
                console.log('error in ', apiUrl, response);
            }
            throw new Error(Request.getErrorMessage(response));
        }
    };


    /**
     * 拼接请求头
     * @param params
     * @param timestamp
     * @return {{timestamp: any}}
     */
    static makeHeaders = (params, timestamp) => {
        return {
            //'Content-type' : 'application/json' ,//js 解决跨域问题(web)
            'timestamp': timestamp,
            // 'device': DeviceInfo.getBrand() + ' ' + DeviceInfo.getModel(),
            // 'device-os-version': DeviceInfo.getSystemVersion(),
            // 'app-version': APP_VERSION,
            // 'signature': signature(params, timestamp)
        }
    };


    /**
     * 打印错误信息
     * @param {Error} e
     * @param from
     * @constructor
     */
    static LogError(e: Error, from: any = null) {
        if (Request.getInstance().debug) {
            if (from) {
                console.log('the error from:', from);
            }
            console.log(e);
        }
        if (e.message === 'Network request failed') {
            Toast.fail('网络请求失败', constant.ToastDuration);
        } else if (e.message === '请登录') {
            RouterServer.replace('auth');
        }
        else {
            Toast.fail(e.message, constant.ToastDuration);
        }
    }


    static LogSuccess = (response: any, frome: string) => {
        if (Request.getInstance().debug) {
            console.log('%c ', 'color"green', frome, response);
        }
    };

    /**
     * post 请求
     * @param {string} url
     * @param {Object} params
     * @return {Promise<Response>}
     */
    static post(url?: string, params?: Object) {
        StatusBar.setNetworkActivityIndicatorVisible(true);
        const apiUrl = Request.getInstance().Api.HOST + url;
        const timestamp = moment().format('X');


        return Request.timeout(Request.getInstance().timeout, fetch(apiUrl, {
            method: 'POST',
            headers: Request.makeHeaders(params, timestamp),
            body: Request.makeFormData(params)
        })).then((response: any) => {
            StatusBar.setNetworkActivityIndicatorVisible(false);
            if (response.ok === true) {
                return response.json();
            } else {
                const e = new Error();
                e.message = '网络错误';
                throw e;
            }
        }).then((responseData) => {

            const checked = Request.checkResponse(responseData, apiUrl);
            if (checked) {
                Request.LogSuccess(responseData, apiUrl);
                return responseData;
            } else {
                return null;
            }
        }).catch((e) => {
            StatusBar.setNetworkActivityIndicatorVisible(false);
            Request.LogError(e, apiUrl);
        });

    }

    /**
     * get
     * @param {string} url
     * @param {Object} params
     * @return {Promise<never | Response>}
     */
    static get(url: string, params?: object) {
        StatusBar.setNetworkActivityIndicatorVisible(true);
        const apiUrl = Request.getInstance().Api.HOST + url + Request.makeQueryString(params);
        return Request.timeout(Request.getInstance().timeout, fetch(apiUrl, {
            method: 'GET',
        })).then((response: any) => {
            StatusBar.setNetworkActivityIndicatorVisible(false);
            if (response.ok === true) {
                return response.json();
            } else {
                const e = new Error();
                e.message = '网络错误';
                throw e;
            }
        }).then((responseData) => {
            const checked = Request.checkResponse(responseData, apiUrl);
            if (checked) {
                Request.LogSuccess(responseData, apiUrl);
                return responseData;
            } else {
                return false;
            }
        }).catch((e) => {
            StatusBar.setNetworkActivityIndicatorVisible(false);
            Request.LogError(e, apiUrl);
        });

        // return fetch(apiUrl, {
        //     method: 'GET',
        // })
        // const responseData = await response.json();
        // if (Request.getInstance().debug) {
        //     console.log(apiUrl, responseData);
        // }
        // const checked = await Request.checkResponse(responseData, apiUrl);
        // if (checked) {
        //     return responseData;
        // } else {
        //     return null;
        // }

    }


    static timeout = (ms: number, promise: Promise<any>) => {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                reject(new Error("请求超时"))
            }, ms);
            promise.then(resolve, reject)
        })
    };

    /**
     *
     * @param {string | {uri: string}} url
     * @return string|any
     */
    static checkImageUrl(url: string | { uri: string }) {
        if (typeof url === 'string') {
            if (Validator.validator(url, Validator.urlReg)) {
                return url;
            } else {
                return Request.getInstance().Api.HOST + url;
            }
        }
        if (Validator.validator(url.uri, Validator.urlReg)) {
            return url;
        } else {
            return {
                ...url, uri: Request.getInstance().Api.HOST + url.uri
            }
        }
    }

    private static getErrorMessage(response: Response) {
        let msg = '';
        if (Array.isArray(response.message)) {

        } else if (typeof response.message === 'string') {
            msg += response.message
        }
        return msg;
    }

}

export default Request;




